/*
 * Copyright (C) 2009 Ionut Dediu <deionut@yahoo.com>
 *
 * Licensed under the GNU General Public License Version 2
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

// SmartCamSettingsList.cpp

#include "SmartCamSettingsList.h"

#include "SmartCam.hrh"
#include "SmartCamSettingsData.h"
#include "SmartCamAppUi.h"
#include "CamFilter.h"

_LIT(KMainCamera, "Main camera");
_LIT(KFrontCamera, "Front camera");

_LIT(KConnUsbStr, "USB");
_LIT(KConnBluetoothStr, "Bluetooth");
_LIT(KConnInetStr, "TCP/IP (WiFi)");

class CCameraIndexSettingItem : public CAknEnumeratedTextPopupSettingItem
	{
public:
	CCameraIndexSettingItem(TInt aIdentifier, TInt& aValue) : 
		CAknEnumeratedTextPopupSettingItem(aIdentifier, aValue)
		{
		}

	void CompleteConstructionL()
		{
		UpdateContentsL();
		}

	void UpdateContentsL()
		{
		CArrayPtr<CAknEnumeratedText>* array = new (ELeave) CArrayPtrFlat<CAknEnumeratedText>(10);
		CArrayPtr<HBufC>* poppedup = new (ELeave) CArrayPtrFlat<HBufC>(10);
		CAknEnumeratedText* mainCamera = new (ELeave) CAknEnumeratedText(0, KMainCamera().AllocL());
		array->AppendL(mainCamera);
		if(CCamFilter::CamerasAvailable() >= 2)
			{
			CAknEnumeratedText* frontCamera = new (ELeave) CAknEnumeratedText(1, KFrontCamera().AllocL());
			array->AppendL(frontCamera);
			}
		SetEnumeratedTextArrays(array, poppedup);
		HandleTextArrayUpdateL();
		}
	};

class CCameraResolutionSettingItem : public CAknEnumeratedTextPopupSettingItem
	{
public:
	CCameraResolutionSettingItem(TInt aIdentifier, TInt& aValue) : 
		CAknEnumeratedTextPopupSettingItem(aIdentifier, aValue)
		{
		}

	void CompleteConstructionL()
		{
		UpdateContentsL();
		}

	void UpdateContentsL()
		{
		CArrayPtr<CAknEnumeratedText>* array = new (ELeave) CArrayPtrFlat<CAknEnumeratedText>(10);
		CArrayPtr<HBufC>* poppedup = new (ELeave) CArrayPtrFlat<HBufC>(10);
		RArray<TSize> resolutions;
		CSmartCamAppUi* smartCamAppUi = static_cast<CSmartCamAppUi*> (CEikonEnv::Static()->EikAppUi());
		smartCamAppUi->EnumerateVideoResolutions(smartCamAppUi->GetSettingsData().CameraSrcIndex(), resolutions);
		for(TInt i = 0; i < resolutions.Count(); i++)
			{
			HBufC* buf = HBufC::NewLC(100);
			buf->Des().Format(_L("%dx%d"), resolutions[i].iWidth, resolutions[i].iHeight);
			array->AppendL(new (ELeave) CAknEnumeratedText(i, buf));
			CleanupStack::Pop(buf);
			}
		TInt& resolution = smartCamAppUi->GetSettingsData().CameraResolutionIndex();
		if(resolution < 0 || resolution >= array->Count())
			resolution = 0;

		SetEnumeratedTextArrays(array, poppedup);
		HandleTextArrayUpdateL();
		}
	};

class CCameraFPSSettingItem : public CAknEnumeratedTextPopupSettingItem
	{
public:
	CCameraFPSSettingItem(TInt aIdentifier, TInt& aValue) : 
		CAknEnumeratedTextPopupSettingItem(aIdentifier, aValue)
		{
		}

	void CompleteConstructionL()
		{
		UpdateContentsL();
		}

	void UpdateContentsL()
		{
		CArrayPtr<CAknEnumeratedText>* array = new (ELeave) CArrayPtrFlat<CAknEnumeratedText>(10);
		CArrayPtr<HBufC>* poppedup = new (ELeave) CArrayPtrFlat<HBufC>(10);
		RArray<TReal32> fpsList;
		CSmartCamAppUi* smartCamAppUi = static_cast<CSmartCamAppUi*> (CEikonEnv::Static()->EikAppUi());
		smartCamAppUi->EnumerateVideoFrameRates(
				smartCamAppUi->GetSettingsData().CameraSrcIndex(), 
				smartCamAppUi->GetSettingsData().CameraResolutionIndex(),
				fpsList);
		for(TInt i = 0; i < fpsList.Count(); i++)
			{
			HBufC* buf = HBufC::NewLC(100);
			buf->Des().Format(_L("%f"), fpsList[i]);
			array->AppendL(new (ELeave) CAknEnumeratedText(i, buf));
			CleanupStack::Pop(buf);
			}
		TInt& fpsIdx = smartCamAppUi->GetSettingsData().CameraFPSIndex();
		if(fpsIdx < 0 || fpsIdx >= array->Count())
			fpsIdx = 0;

		SetEnumeratedTextArrays(array, poppedup);
		HandleTextArrayUpdateL();
		}
	};

class CConnectionTypeSettingItem : public CAknEnumeratedTextPopupSettingItem
	{
public:
	CConnectionTypeSettingItem(TInt aIdentifier, TInt& aValue) : 
		CAknEnumeratedTextPopupSettingItem(aIdentifier, aValue)
		{
		}

	void CompleteConstructionL()
		{
		UpdateContentsL();
		}

	void UpdateContentsL()
		{
		CArrayPtr<CAknEnumeratedText>* array = new (ELeave) CArrayPtrFlat<CAknEnumeratedText>(10);
		CArrayPtr<HBufC>* poppedup = new (ELeave) CArrayPtrFlat<HBufC>(10);

		CAknEnumeratedText* connUsb = new (ELeave) CAknEnumeratedText(EConnectionUsb, KConnUsbStr().AllocL());
		array->AppendL(connUsb);
		CAknEnumeratedText* connBluetooth = new (ELeave) CAknEnumeratedText(EConnectionBluetooth, KConnBluetoothStr().AllocL());
		array->AppendL(connBluetooth);
		CAknEnumeratedText* connInet = new (ELeave) CAknEnumeratedText(EConnectionInet, KConnInetStr().AllocL());
		array->AppendL(connInet);

		SetEnumeratedTextArrays(array, poppedup);
		HandleTextArrayUpdateL();
		}
	};

CSmartCamSettingsList* CSmartCamSettingsList::NewL(CSmartCamSettingsData& aSettingsData)
	{
	CSmartCamSettingsList* self = CSmartCamSettingsList::NewLC(aSettingsData);
	CleanupStack::Pop(self);
	return self;
	}

CSmartCamSettingsList* CSmartCamSettingsList::NewLC(CSmartCamSettingsData& aSettingsData)
	{
	CSmartCamSettingsList* self = new (ELeave) CSmartCamSettingsList(aSettingsData);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CSmartCamSettingsList::CSmartCamSettingsList(CSmartCamSettingsData& aSettingsData) :
	CAknSettingItemList(),
	iSettingsData(aSettingsData),
	iBtDiscoverer(NULL)
	{
	}

void CSmartCamSettingsList::ConstructL()
	{
	}

CSmartCamSettingsList::~CSmartCamSettingsList()
	{
	if(iBtDiscoverer != NULL)
		{
		delete iBtDiscoverer;
		iBtDiscoverer = NULL;
		}
	}

void CSmartCamSettingsList::SizeChanged()
    {
	// if size changes, make sure component takes whole available space
	CEikFormattedCellListBox* listbox = ListBox();
    if (listbox)
        {
        listbox->SetRect(Rect());
        }
    }

void CSmartCamSettingsList::UpdateSettingItemsVisibility()
	{
	CAknSettingItemArray* array = SettingItemArray();
	// For USB connection hide inet server, bt server and inet port fields
	if(iSettingsData.ConnectionType() == EConnectionUsb)
		{
		for(TInt i = 0; i < array->Count(); i++)
			{
			CAknSettingItem* curItem = (*array)[i];
			if((curItem->Identifier() == ESettingInetServerAddr) || 
			   (curItem->Identifier() == ESettingBtServerAddr) ||
			   (curItem->Identifier() == ESettingInetPort))
				{
				curItem->SetHidden(ETrue);
				}
			}
		}
	// For Bluetooth connection hide inet server and inet port fields
	// and show bt server
	if(iSettingsData.ConnectionType() == EConnectionBluetooth)
		{
		for(TInt i = 0; i < array->Count(); i++)
			{
			CAknSettingItem* curItem = (*array)[i];
			if((curItem->Identifier() == ESettingInetServerAddr) || 
			   (curItem->Identifier() == ESettingInetPort))
				{
				curItem->SetHidden(ETrue);
				}
			if(curItem->Identifier() == ESettingBtServerAddr)
				{
				curItem->SetHidden(EFalse);
				}
			}
		}
	// For inet connection hide bt server
	// and show inet server and inet port fields
	if(iSettingsData.ConnectionType() == EConnectionInet)
		{
		for(TInt i = 0; i < array->Count(); i++)
			{
			CAknSettingItem* curItem = (*array)[i];
			if((curItem->Identifier() == ESettingInetServerAddr) || 
			   (curItem->Identifier() == ESettingInetPort))
				{
				curItem->SetHidden(EFalse);
				}
			if(curItem->Identifier() == ESettingBtServerAddr)
				{
				curItem->SetHidden(ETrue);
				}
			}
		}
	}

void CSmartCamSettingsList::EditItemL(TInt aIndex, TBool aCalledFromMenu)
	{
	CAknSettingItem* item = (*SettingItemArray())[aIndex];
	if(item->Identifier() == ESettingBtServerAddr)
		{
		StartBtDiscovery();
		return;
		}
	CAknSettingItemList::EditItemL(aIndex, aCalledFromMenu);
	item->StoreL();
	if(item->Identifier() == ESettingCameraResolution)
		{
		static_cast<CCameraResolutionSettingItem*>(item)->UpdateContentsL();
		}
	else if(item->Identifier() == ESettingCameraIndex)
		{
		CAknSettingItemArray* array = SettingItemArray();
		// update camera resolution list
		for(TInt i = 0; i < array->Count(); i++)
			{
			CAknSettingItem* curItem = (*array)[i];
			if(curItem->Identifier() == ESettingCameraResolution)
				{
				static_cast<CCameraResolutionSettingItem*>(curItem)->UpdateContentsL();
				break;
				}
			}
		// update camera FPS list
		for(TInt i = 0; i < array->Count(); i++)
			{
			CAknSettingItem* curItem = (*array)[i];
			if(curItem->Identifier() == ESettingCameraFPS)
				{
				static_cast<CCameraFPSSettingItem*>(curItem)->UpdateContentsL();
				break;
				}
			}
		}
	else if(item->Identifier() == ESettingCameraResolution)
		{
		CAknSettingItemArray* array = SettingItemArray();
		// update camera FPS list
		for(TInt i = 0; i < array->Count(); i++)
			{
			CAknSettingItem* curItem = (*array)[i];
			if(curItem->Identifier() == ESettingCameraFPS)
				{
				static_cast<CCameraFPSSettingItem*>(curItem)->UpdateContentsL();
				break;
				}
			}
		}
	else if(item->Identifier() == ESettingConnectionType)
		{
		UpdateSettingItemsVisibility();
		}
	HandleChangeInItemArrayOrVisibilityL();
	}

void CSmartCamSettingsList::StartBtDiscovery()
	{
	if(iBtDiscoverer != NULL)
		{
		delete iBtDiscoverer;
		iBtDiscoverer = NULL;
		}
	iBtDiscoverer = CBtDiscoverer::NewL(*this);
	iBtDiscoverer->SelectRemoteDevice();
	}

void CSmartCamSettingsList::RemoteDeviceSelected(TInt aErrorCode)
	{
	if(aErrorCode == KErrNone && iBtDiscoverer->IsValidBDAddr())
		{
		CAknSettingItemArray* array = SettingItemArray();
		for(TInt i = 0; i < array->Count(); i++)
			{
			CAknSettingItem* curItem = (*array)[i];
			if(curItem->Identifier() == ESettingBtServerAddr)
				{
				TDes& oldBtAddr = iSettingsData.BtServerAddr();
				iBtDiscoverer->BTDevAddr().GetReadable(oldBtAddr);

				TDes& oldBtName = iSettingsData.BtServerFriendlyName();
				oldBtName.Copy(iBtDiscoverer->BTDevName());

				curItem->LoadL();
				curItem->UpdateListBoxTextL();
				DrawNow();
				break;
				}
			}
		}

	if(iBtDiscoverer != NULL)
		{
		delete iBtDiscoverer;
		iBtDiscoverer = NULL;
		}
	}

void CSmartCamSettingsList::RemoteServiceFound(TInt aErrorCode)
	{
	
	}

CAknSettingItem * CSmartCamSettingsList::CreateSettingItemL(TInt aIdentifier)
	{
	CAknSettingItem* settingItem = NULL;

    switch(aIdentifier)
		{
		case ESettingCameraIndex:
			settingItem = new (ELeave) CCameraIndexSettingItem(
											aIdentifier, 
											iSettingsData.CameraSrcIndex());
			break;
		case ESettingCameraResolution:
			settingItem = new (ELeave) CCameraResolutionSettingItem(
											aIdentifier,
											iSettingsData.CameraResolutionIndex());
			break;
		case ESettingCameraFPS:
			settingItem = new (ELeave) CCameraFPSSettingItem(
											aIdentifier,
											iSettingsData.CameraFPSIndex());
			break;
		case ESettingConnectionType:
			settingItem = new (ELeave) CConnectionTypeSettingItem(
											aIdentifier,
											iSettingsData.ConnectionType());
			break;
		case ESettingInetServerAddr:
			settingItem = new (ELeave) CAknTextSettingItem(
											aIdentifier,
											iSettingsData.InetServer());
			// For USB or BT connection hide inet server
			if(iSettingsData.ConnectionType() == EConnectionUsb || iSettingsData.ConnectionType() == EConnectionBluetooth)
				{
				settingItem->SetHidden(ETrue);
				}
			else
				{
				settingItem->SetHidden(EFalse);
				}
			break;
		case ESettingBtServerAddr:
			settingItem = new (ELeave) CAknTextSettingItem(
											aIdentifier,
											iSettingsData.BtServerFriendlyName());
			// For USB or inet connection hide BT server
			if(iSettingsData.ConnectionType() == EConnectionUsb || iSettingsData.ConnectionType() == EConnectionInet)
				{
				settingItem->SetHidden(ETrue);
				}
			else
				{
				settingItem->SetHidden(EFalse);
				}
			break;
		case ESettingInetPort:
			settingItem = new (ELeave) CAknIntegerEdwinSettingItem(
											aIdentifier,
							 				iSettingsData.InetPort());
			// For USB or BT connection hide inet port
			if(iSettingsData.ConnectionType() == EConnectionUsb || iSettingsData.ConnectionType() == EConnectionBluetooth)
				{
				settingItem->SetHidden(ETrue);
				}
			else
				{
				settingItem->SetHidden(EFalse);
				}
			break;
		}
    return settingItem;
	}

